#include "syntax_tree.h"
#include "semantic_analyzer.h"
#include "main_container.h"
#include "errors_warnings.h"
extern MainContainer * CompilerData;



//(Gr_Simulation__simulation_NAME_spLCBrac_SimulationBody_spRCBrac)

SemanticsSimulation * SemanticAnalyzer::GatherFromSimulation(SyntaxTreeNode * simulationNode, int parentContext)
{
#ifdef TRACE
	CompilerData->LogTrace->ReportEntry("GatherFromSimulation");
#endif
	SemanticsSimulation *ss;
	ss = new SemanticsSimulation();

	if(simulationNode->Production == Gr_Simulation__simulation_NAME_spLCBrac_SimulationBody_spRCBrac)
	{
		SyntaxTreeNode * simulationBodyNode = simulationNode->Nodes->GetData(3);
		// <simulation_body> ~ <simulation_stmt> <simulation_body>
		ss->Body->Add( ReadSimulationStatement(simulationBodyNode) );
	}
	else
	{
		// ERROR has been found
		// MAKE LOGICAL RECOVERING
	}

#ifdef TRACE
	CompilerData->LogTrace->ReportExit("GatherFromSimulation");
#endif
	return ss;
}


//(Gr_SimulationBody__SimulationStmt_SimulationBody, ostale Gr_SimulationStmt__*****)
SemanticsSimulationStatement * SemanticAnalyzer::ReadSimulationStatement(SyntaxTreeNode * simulationStatementNode)
{
#ifdef TRACE
	CompilerData->LogTrace->ReportEntry("ReadSimulationStatement");
#endif

	SemanticsSimulationStatement *sss;
	sss = new SemanticsSimulationStatement();

	if(simulationStatementNode->Production == Gr_SimulationBody__SimulationStmt_SimulationBody)
	{
		SyntaxTreeNode * simulationStmtNode = simulationStatementNode->Nodes->GetData(0);
		if(simulationStmtNode->Production == Gr_SimulationStmt__SimClear) 
		{
			SemanticsSimulationStatementType *ssst;
			ssst = new SemanticsSimulationStatementType();
			ssst[0] = SimStatClear;
			sss->Type = ssst;
		}
		else if(simulationStmtNode->Production == Gr_SimulationStmt__SimConfiguration) 
		{
			SemanticsSimulationStatementType *ssst;
			ssst = new SemanticsSimulationStatementType();
			ssst[0] = SimStatConfiguration;
			sss->Type = ssst;
		}
		else if(simulationStmtNode->Production == Gr_SimulationStmt__SimReset) 
		{
			SemanticsSimulationStatementType *ssst;
			ssst = new SemanticsSimulationStatementType();
			ssst[0] = SimStatReset;
			sss->Type = ssst;
		}
		else if(simulationStmtNode->Production == Gr_SimulationStmt__SimRun) 
		{
			SemanticsSimulationStatementType *ssst;
			ssst = new SemanticsSimulationStatementType();
			ssst[0] = SimStatRun;
			sss->Type = ssst;
		}
	}
	else
	{
		// ERROR has been found
		// MAKE LOGICAL RECOVERING
	}

#ifdef TRACE
	CompilerData->LogTrace->ReportEntry("ReadSimulationStatement");
#endif
	return sss;
}

//(Gr_SimConfiguration__configuration_Name_spLPar_Arguments_spRPar_spSemiCol)
SemanticsSimStatConfiguration * SemanticAnalyzer::ReadSimConfiguration(SyntaxTreeNode * simStConfigurationNode)
{
#ifdef TRACE
	CompilerData->LogTrace->ReportEntry("ReadSimConfiguration");
#endif

	SemanticsSimStatConfiguration *ssc;
	ssc = new SemanticsSimStatConfiguration();

	if(simStConfigurationNode->Production == Gr_SimConfiguration__configuration_Name_spLPar_Arguments_spRPar_spSemiCol)
	{
		SyntaxTreeNode * nameNode = simStConfigurationNode->Nodes->GetData(1);
		ssc->Name= GatherFromNameNode(nameNode);
		SyntaxTreeNode * argumentsNode = simStConfigurationNode->Nodes->GetData(3);
		// <arguments> ~ <expression> <arguments_add>
		SyntaxTreeNode * expressionNode = argumentsNode->Nodes->GetData(0);
		SyntaxTreeNode * argumentsAddNode = argumentsNode->Nodes->GetData(1);
		for(int i=0; i < argumentsAddNode->Nodes->GetCount(); i++)
			{
				// <arguments_add> ~ <argument_comma_add> <arguments_add>
				// <argument_comma_add> ~ , <expression>
				SyntaxTreeNode * argumentsCommaAddNode = argumentsAddNode->Nodes->GetData(i);
				ssc->Parameters->Add(GatherFromExpression(argumentsCommaAddNode->Nodes->GetData(1)));
			}	
	}
	else
	{
		// ERROR has been found
		// MAKE LOGICAL RECOVERING
	}

#ifdef TRACE
	CompilerData->LogTrace->ReportExit("ReadSimConfiguration");
#endif
	return ssc;
}

//(Gr_SimRun__run_Expression_simulations_UptoExpression_spSemiCol 
// ,Gr_SimRun__run_UptoExpression_spSemiCol)
SemanticsSimStatRun * SemanticAnalyzer::ReadSimRun(SyntaxTreeNode * simStRunNode)
{
#ifdef TRACE
	CompilerData->LogTrace->ReportEntry("ReadSimRun");
#endif
	
	SemanticsSimStatRun *ssr;
	ssr = new SemanticsSimStatRun();
	if(simStRunNode->Production == Gr_SimRun__run_Expression_simulations_UptoExpression_spSemiCol)
	{
		SyntaxTreeNode * expressionNode = simStRunNode->Nodes->GetData(1);
		SyntaxTreeNode * uptoExpressionNode = simStRunNode->Nodes->GetData(3);
		ssr->Expression = GatherFromExpression(expressionNode);

		// <upto_expression> ~ upto <expression>  {upto}
		// <upto_expression> ~ ? {NAME, after, every, ;, send}
		if (uptoExpressionNode->Nodes->GetCount())
			ssr->UptoExpression = GatherFromExpression(uptoExpressionNode->Nodes->GetData(1));

	}
	else if (simStRunNode->Production == Gr_SimRun__run_UptoExpression_spSemiCol)
	{
		SyntaxTreeNode * uptoExpressionNode = simStRunNode->Nodes->GetData(1);
		if (uptoExpressionNode->Nodes->GetCount())
			ssr->UptoExpression = GatherFromExpression(uptoExpressionNode->Nodes->GetData(1));

	}
	else
	{
		// ERROR has been found
		// MAKE LOGICAL RECOVERING
	}

#ifdef TRACE
	CompilerData->LogTrace->ReportExit("ReadSimRun");
#endif
	return ssr;
}

//(Gr_SimClear__clear_spSemiCol)
SemanticsSimStatClear * SemanticAnalyzer::ReadSimClear(SyntaxTreeNode * simStClear)
{
#ifdef TRACE
	CompilerData->LogTrace->ReportEntry("ReadSimClear");
#endif

	SemanticsSimStatClear *sssc;
	sssc = new SemanticsSimStatClear();

	if(simStClear->Production == Gr_SimClear__clear_spSemiCol)
	{
	}
	else
	{
		// ERROR has been found
		// MAKE LOGICAL RECOVERING
	}

#ifdef TRACE
	CompilerData->LogTrace->ReportExit("ReadSimClear");
#endif
	return sssc;
}


//(Gr_SimReset__reset_spSemiCol)
SemanticsSimStatReset * SemanticAnalyzer::ReadSimReset(SyntaxTreeNode * simStReset)
{
#ifdef TRACE
	CompilerData->LogTrace->ReportEntry("ReadSimReset");
#endif

	SemanticsSimStatReset *sssr;
	sssr = new SemanticsSimStatReset();

	if(simStReset->Production == Gr_SimReset__reset_spSemiCol)
	{
	}
	else
	{
		// ERROR has been found
		// MAKE LOGICAL RECOVERING
	}

#ifdef TRACE
	CompilerData->LogTrace->ReportExit("ReadSimReset");
#endif
	return sssr;
}



//( Gr_Name__NAME_NameAdd, NAME)
GenericTable<int> * SemanticAnalyzer::GatherFromNameNode(SyntaxTreeNode * nameNode)
{
#ifdef TRACE
	CompilerData->LogTrace->ReportEntry("GatherFromNameNode");
#endif
	int i;
	
	GenericTable<int> * gt = new GenericTable<int>();

    //NAME	
	if((nameNode->Production == Gr_Terminal) && 
	   (CompilerData->Units->GetLexicUnit(nameNode->LexUnitID)).type == LUTypeIdentifier )
	{
		int * tempData = new int;
		LexicUnit lu = CompilerData->Units->GetLexicUnit(nameNode->LexUnitID);
		* tempData = lu.subtype; // TODO - was .subtype (wrong obviously)
		gt->Add(tempData);
	}

	// <name> ~ NAME <name_add>
	else if(nameNode->Production == Gr_Name__NAME_NameAdd)
	{
		SyntaxTreeNode * lexicNameNode = nameNode->Nodes->GetData(0);
		int * tempData = new int;
		LexicUnit lu = CompilerData->Units->GetLexicUnit((nameNode->Nodes->GetData(0))->LexUnitID);
		* tempData = lu.subtype; // TODO - was .subtype (wrong obviously)
		gt->Add(tempData); 
		
		SyntaxTreeNode * nameAddNode = nameNode->Nodes->GetData(1);
		//<name_add> ~ <name_period_add> <name_add>
		//<name_period_add> ~ . NAME
		for (i = 0; i < nameAddNode->Nodes->GetCount(); i++) 
		{
			SyntaxTreeNode * namePeriodAddNode = nameAddNode->Nodes->GetData(i);
			SyntaxTreeNode * nameNodeI = namePeriodAddNode->Nodes->GetData(1);
			int * tempData2 = new int;
			LexicUnit lu2 = CompilerData->Units->GetLexicUnit(nameNodeI->LexUnitID);
			* tempData2 = lu2.subtype; // TODO - was .subtype (wrong obviously)

			gt->Add(tempData2);
		}
	}
	else
	{
		 //ERROR has been found
		 //MAKE LOGICAL RECOVERING
	}

#ifdef TRACE
	CompilerData->LogTrace->ReportExit("GatherFromNameNode");
#endif
	return gt;
}
